package org.copper.ui
{
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import org.copper.ui.events.MouseEnterGraphicContentEvent;
	import org.copper.ui.events.MouseLeaveGraphicContentEvent;
	import org.copper.ui.events.MouseOverGraphicContentEvent;
	import org.copper.ui.interfaces.ItemRenderer;

	public class CSprite extends Sprite implements ItemRenderer
	{
		private const m_copyMatrix:Matrix = new Matrix();
		
		private var m_data:Object = null;
		
		private var m_prevOverFlag:Boolean = false;
		private var m_graphicsContextualEventsEnabled:Boolean = false;
		private var m_considerTransperent:Number = 0.7;
		private var m_eventsProvider:DisplayObject;
		
		public function CSprite()
		{
			super();
			m_eventsProvider = this;
		}
		
		public function get eventsProvider():DisplayObject
		{
			return m_eventsProvider;
		}
		
		public function set eventsProvider(value:DisplayObject):void
		{
			if (m_graphicsContextualEventsEnabled)
			{
				unbindeventsProvider(m_eventsProvider);
				bindeventsProvider(value);
			}
			m_eventsProvider = value;
		}
		
		private function enableGraphicsContextualEvents():void
		{
			bindeventsProvider(m_eventsProvider);
		}
		
		
		private function disableGraphicsContextualEvents():void
		{
			unbindeventsProvider(m_eventsProvider);
		}
		
		private function bindeventsProvider(obj:DisplayObject):void
		{
			if (obj == null)
				return;
			
			obj.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		}
		
		private function unbindeventsProvider(obj:DisplayObject):void
		{
			if (obj == null)
				return;
			
			obj.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		}
		
		private function onMouseMove(event:MouseEvent):void
		{
			const isOverFlag:Boolean = this.isMouseOnContent(m_considerTransperent);
			
			if (isOverFlag != m_prevOverFlag)
			{
				m_prevOverFlag = isOverFlag;
				if (isOverFlag)
				{
					dispatchEvent(new MouseEnterGraphicContentEvent(event, this));
				}
				else
				{
					dispatchEvent(new MouseLeaveGraphicContentEvent(event, this));
				}
			}
			
			if (isOverFlag)
			{
				dispatchEvent(new MouseOverGraphicContentEvent(event, this));
			}
		}
		
		public function get graphicsContextualEventsEnabled():Boolean
		{
			return m_graphicsContextualEventsEnabled;
		}
		
		public function set graphicsContextualEventsEnabled(value:Boolean):void
		{
			if (value != m_graphicsContextualEventsEnabled)
			{
				m_graphicsContextualEventsEnabled = value;
				if (value)
				{
					enableGraphicsContextualEvents();
				}
				else
				{
					disableGraphicsContextualEvents();
				}
			}
		}
		
		public function get considerTransperent():Number
		{
			return m_considerTransperent;
		}
		
		public function set considerTransperent(value:Number):void
		{
			m_considerTransperent = value;
		}
		
		public function snapShot():BitmapData
		{
			return snapShotRect(this.getRect(this));
		}
		
		public function snapShotRect(bounds:Rectangle):BitmapData
		{
			const ans:BitmapData  = new BitmapData(bounds.width, bounds.height, true, 0);
			const m:Matrix = m_copyMatrix;
			m.tx = -bounds.x;
			m.ty = -bounds.y;
			ans.draw(this, m);
			return ans;
		}
		
		public function get data():Object
		{
			return m_data;
		}
		
		public function set data(value:Object):void
		{
			m_data = value;
		}
		
		public function isPointOnContent(X:Number, Y:Number, alphaThreshold:Number = 0.7):Boolean
		{
			const rect:Rectangle = this.getRect(this);
			const rx:Number = rect.x;
			const ry:Number = rect.y;
			
			if (X < rx || Y < ry)
				return false;
			
			const rw:Number = rect.width;
			const rh:Number = rect.height;
			
			if (X > rx + rw || Y > ry + rw)
				return false;
			
			const bd:BitmapData = new BitmapData(rw, rh, true, 0);
			const m:Matrix = m_copyMatrix;
			m.tx = -rx;
			m.ty = -ry;
			bd.draw(this, m);
			
			const alpha:Number = bd.getPixel32(X - rx, Y - ry) >> 24 & 0xFF;
			bd.dispose();
			if (alpha > (alphaThreshold * 255))
				return true;
			else
				return false
		}
		
		
		public function isMouseOnContent(alphaThreshold:Number = 0.7):Boolean
		{
			const stg:Stage = this.stage;
			
			if (stg == null)
				return false;
			
			const localMouse:Point = this.globalToLocal(new Point(stg.mouseX, stg.mouseY));
			
			return isPointOnContent(localMouse.x, localMouse.y, alphaThreshold);
		}
		
		public function init():void{}
		
		public function recycle():void{}
		
		public function dispose():void{}
	}
}